"""
简化的数据模型和配置结构

这个模块包含了重构后系统使用的简化数据模型，移除了复杂的工序分类逻辑，
只保留核心的调度优化所需的数据结构。
"""

from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional


class OptimizationObjective(Enum):
    """优化目标枚举"""

    MINIMIZE_MAKESPAN = "minimize_makespan"
    MINIMIZE_COST = "minimize_cost"
    RESOURCE_LEVELING = "resource_leveling"


@dataclass
class WorkerType:
    """工种类型数据模型
    
    定义工种的基本信息和容量限制
    """
    
    name: str
    capacity: int
    
    def __post_init__(self):
        """验证工种数据"""
        if not self.name or not self.name.strip():
            raise ValueError("工种名称不能为空")
            
        if self.capacity <= 0:
            raise ValueError(f"工种容量必须大于0，当前值: {self.capacity}")
            
        # 标准化工种名称
        self.name = self.name.strip()


@dataclass
class ResourceCapacity:
    """资源容量配置

    定义单个资源类型的容量限制
    """

    resource_type: str
    capacity: int

    def __post_init__(self):
        """验证资源容量配置"""
        if not self.resource_type or not self.resource_type.strip():
            raise ValueError("资源类型不能为空")

        if self.capacity <= 0:
            raise ValueError(f"资源容量必须大于0，当前值: {self.capacity}")

        # 标准化资源类型名称（转为小写）
        self.resource_type = self.resource_type.strip().lower()


@dataclass
class SubdivisionConfig:
    """分区规划配置

    控制工序分区的参数设置
    """

    subdivision_count: int = 2
    resource_efficiency: float = 0.75
    enable_subdivision: bool = True

    def __post_init__(self):
        """验证分区配置参数"""
        if self.subdivision_count < 1:
            raise ValueError(f"分区数量必须大于等于1，当前值: {self.subdivision_count}")

        if not (0.1 <= self.resource_efficiency <= 1.0):
            raise ValueError(
                f"资源效率必须在0.1-1.0之间，当前值: {self.resource_efficiency}"
            )


@dataclass
class OptimizationConfig:
    """优化配置参数

    包含所有优化求解相关的配置参数
    """

    resource_capacities: List[ResourceCapacity] = field(default_factory=list)
    subdivision_config: SubdivisionConfig = field(default_factory=SubdivisionConfig)
    optimization_objective: str = OptimizationObjective.MINIMIZE_MAKESPAN.value
    solve_time_limit: int = 300

    def __post_init__(self):
        """验证优化配置参数"""
        # 验证求解时间限制
        if self.solve_time_limit <= 0:
            raise ValueError(
                f"求解时间限制必须大于0秒，当前值: {self.solve_time_limit}"
            )

        # 验证优化目标
        valid_objectives = [obj.value for obj in OptimizationObjective]
        if self.optimization_objective not in valid_objectives:
            raise ValueError(
                f"无效的优化目标: {self.optimization_objective}，"
                f"有效选项: {valid_objectives}"
            )

        # 设置默认资源容量（如果为空）
        if not self.resource_capacities:
            self.resource_capacities = [
                ResourceCapacity("worker", 20),
                ResourceCapacity("excavator", 5),
            ]

        # 验证资源容量配置的唯一性
        resource_types = [rc.resource_type for rc in self.resource_capacities]
        if len(resource_types) != len(set(resource_types)):
            raise ValueError("资源类型配置中存在重复项")

    def get_resource_capacity(self, resource_type: str) -> int:
        """获取指定资源类型的容量"""
        resource_type = resource_type.strip().lower()
        for rc in self.resource_capacities:
            if rc.resource_type == resource_type:
                return rc.capacity
        return 0

    def add_resource_capacity(self, resource_type: str, capacity: int):
        """添加资源容量配置"""
        # 检查是否已存在
        resource_type = resource_type.strip().lower()
        for rc in self.resource_capacities:
            if rc.resource_type == resource_type:
                rc.capacity = capacity
                return

        # 添加新的资源容量配置
        self.resource_capacities.append(ResourceCapacity(resource_type, capacity))

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            "resource_capacities": [
                {"resource_type": rc.resource_type, "capacity": rc.capacity}
                for rc in self.resource_capacities
            ],
            "subdivision_config": {
                "subdivision_count": self.subdivision_config.subdivision_count,
                "resource_efficiency": self.subdivision_config.resource_efficiency,
                "enable_subdivision": self.subdivision_config.enable_subdivision,
            },
            "optimization_objective": self.optimization_objective,
            "solve_time_limit": self.solve_time_limit,
        }


@dataclass
class Activity:
    """简化的工序数据模型

    移除了复杂的工序分类逻辑，只保留核心调度信息
    """

    id: int
    name: str
    duration: int
    can_subdivide: bool = False

    # 可选的扩展信息
    original_duration: Optional[int] = None
    subdivided: bool = False
    
    # 工种需求信息
    worker_requirements: Dict[str, int] = field(default_factory=dict)

    def __post_init__(self):
        """验证工序数据"""
        if self.id <= 0:
            raise ValueError(f"工序ID必须大于0，当前值: {self.id}")

        if not self.name or not self.name.strip():
            raise ValueError("工序名称不能为空")

        if self.duration <= 0:
            raise ValueError(f"工序工期必须大于0，当前值: {self.duration}")

        # 标准化工序名称
        self.name = self.name.strip()

        # 如果没有设置原始工期，则使用当前工期
        if self.original_duration is None:
            self.original_duration = self.duration

    def apply_subdivision(self, subdivision_count: int, resource_efficiency: float):
        """应用分区逻辑到工序"""
        if not self.can_subdivide:
            return

        if subdivision_count < 1:
            raise ValueError("分区数量必须大于等于1")

        if not (0.1 <= resource_efficiency <= 1.0):
            raise ValueError("资源效率必须在0.1-1.0之间")

        # 计算分区后的工期
        new_duration = max(
            1, int(self.duration / subdivision_count * resource_efficiency)
        )

        if new_duration != self.duration:
            self.duration = new_duration
            self.subdivided = True

    def reset_subdivision(self):
        """重置分区状态，恢复原始工期"""
        if self.subdivided and self.original_duration:
            self.duration = self.original_duration
            self.subdivided = False
    
    def get_total_workers(self) -> int:
        """获取总工人需求"""
        return sum(self.worker_requirements.values())
    
    def add_worker_requirement(self, worker_type: str, count: int):
        """添加工种需求"""
        if count <= 0:
            raise ValueError(f"工人数量必须大于0，当前值: {count}")
        
        worker_type = worker_type.strip()
        if not worker_type:
            raise ValueError("工种类型不能为空")
            
        self.worker_requirements[worker_type] = count
    
    def get_worker_requirement(self, worker_type: str) -> int:
        """获取指定工种的需求数量"""
        return self.worker_requirements.get(worker_type.strip(), 0)


@dataclass
class Precedence:
    """前置关系数据模型"""

    from_activity: int
    to_activity: int
    dependency_type: str = "FS"  # FS, SS, FF, SF
    lag: int = 0

    def __post_init__(self):
        """验证前置关系数据"""
        if self.from_activity <= 0 or self.to_activity <= 0:
            raise ValueError("工序ID必须大于0")

        if self.from_activity == self.to_activity:
            raise ValueError("工序不能依赖自己")

        valid_types = ["FS", "SS", "FF", "SF"]
        if self.dependency_type not in valid_types:
            raise ValueError(
                f"无效的依赖类型: {self.dependency_type}，" f"有效选项: {valid_types}"
            )


@dataclass
class ProjectData:
    """项目数据容器

    包含完整的项目调度数据
    """

    activities: List[Activity] = field(default_factory=list)
    precedences: List[Precedence] = field(default_factory=list)
    resources: Dict[str, int] = field(default_factory=dict)
    resource_demands: Dict[str, Dict[str, int]] = field(default_factory=dict)

    def __post_init__(self):
        """验证项目数据完整性"""
        # 验证工序ID唯一性
        activity_ids = [act.id for act in self.activities]
        if len(activity_ids) != len(set(activity_ids)):
            raise ValueError("工序ID存在重复")

        # 验证前置关系引用的工序存在
        for prec in self.precedences:
            if prec.from_activity not in activity_ids:
                raise ValueError(f"前置关系引用了不存在的工序ID: {prec.from_activity}")
            if prec.to_activity not in activity_ids:
                raise ValueError(f"前置关系引用了不存在的工序ID: {prec.to_activity}")

    def get_activity_by_id(self, activity_id: int) -> Optional[Activity]:
        """根据ID获取工序"""
        for activity in self.activities:
            if activity.id == activity_id:
                return activity
        return None

    def add_activity(self, activity: Activity):
        """添加工序"""
        # 检查ID是否已存在
        if self.get_activity_by_id(activity.id):
            raise ValueError(f"工序ID {activity.id} 已存在")

        self.activities.append(activity)

    def add_precedence(self, precedence: Precedence):
        """添加前置关系"""
        # 验证引用的工序存在
        if not self.get_activity_by_id(precedence.from_activity):
            raise ValueError(
                f"前置关系引用了不存在的工序ID: {precedence.from_activity}"
            )
        if not self.get_activity_by_id(precedence.to_activity):
            raise ValueError(f"前置关系引用了不存在的工序ID: {precedence.to_activity}")

        self.precedences.append(precedence)

    def get_subdividable_activities(self) -> List[Activity]:
        """获取所有可分区的工序"""
        return [act for act in self.activities if act.can_subdivide]

    def apply_subdivision_config(self, subdivision_config: SubdivisionConfig):
        """对所有可分区工序应用分区配置"""
        if not subdivision_config.enable_subdivision:
            return

        subdividable_activities = self.get_subdividable_activities()
        for activity in subdividable_activities:
            activity.apply_subdivision(
                subdivision_config.subdivision_count,
                subdivision_config.resource_efficiency,
            )


# 配置验证工具函数
def validate_config_dict(config_dict: Dict[str, Any]) -> OptimizationConfig:
    """验证并创建配置对象

    Args:
        config_dict: 配置字典

    Returns:
        验证后的OptimizationConfig对象

    Raises:
        ValueError: 配置参数无效时
    """
    try:
        # 解析资源容量配置
        resource_capacities = []
        if "resource_capacities" in config_dict:
            for rc_dict in config_dict["resource_capacities"]:
                resource_capacities.append(
                    ResourceCapacity(
                        resource_type=rc_dict["resource_type"],
                        capacity=rc_dict["capacity"],
                    )
                )

        # 解析分区配置
        subdivision_config = SubdivisionConfig()
        if "subdivision_config" in config_dict:
            sc_dict = config_dict["subdivision_config"]
            subdivision_config = SubdivisionConfig(
                subdivision_count=sc_dict.get("subdivision_count", 2),
                resource_efficiency=sc_dict.get("resource_efficiency", 0.75),
                enable_subdivision=sc_dict.get("enable_subdivision", True),
            )

        # 创建优化配置
        optimization_config = OptimizationConfig(
            resource_capacities=resource_capacities,
            subdivision_config=subdivision_config,
            optimization_objective=config_dict.get(
                "optimization_objective", OptimizationObjective.MINIMIZE_MAKESPAN.value
            ),
            solve_time_limit=config_dict.get("solve_time_limit", 300),
        )

        return optimization_config

    except KeyError as e:
        raise ValueError(f"配置参数缺失: {e}")
    except Exception as e:
        raise ValueError(f"配置参数验证失败: {e}")


def create_default_config() -> OptimizationConfig:
    """创建默认配置"""
    return OptimizationConfig(
        resource_capacities=[
            ResourceCapacity("worker", 20),
            ResourceCapacity("excavator", 5),
            ResourceCapacity("crane", 2),
        ],
        subdivision_config=SubdivisionConfig(
            subdivision_count=2, resource_efficiency=0.75, enable_subdivision=True
        ),
        optimization_objective=OptimizationObjective.MINIMIZE_MAKESPAN.value,
        solve_time_limit=300,
    )
